﻿//
// Created by hujin on 2020/10/6.
//

#include "ast_def.h"
#include "../logger.h"

void CnstDefNode::addToTable(SymbolTable* table) {
	for (const auto& x : val) {
        Identifier_Data data = Identifier_Data(isInt ? ID_CNST_I : ID_CNST_C);
        data.cnstData = x.second;
        if(!table->pushSymbol(x.first, data)){
            log_error(3, "dup cnst name", getLine(), getPos());
            log_error2('b', getLine());
		}

	}

}

void VarDefNode::addToTable(SymbolTable* table) {
	for (auto x : data) {
		if (x->dimension == 0) {
			if(!table->pushSymbol(x->name, Identifier_Data(isInt ? ID_VAR_I : ID_VAR_C))){
                log_error(3, "dup var name", getLine(), getPos());
                log_error2('b', getLine());
			}
            x->dat = table->getDiscriptions(x->name);
            continue;
		}
		if (x->dimension == 1) {
			Identifier_Data id_data = Identifier_Data(isInt ? ID_ARR_I : ID_ARR_C);
			id_data.size[0] = x->size[0];
			if(!table->pushSymbol(x->name, id_data)){
                log_error(3, "dup var name", getLine(), getPos());
                log_error2('b', getLine());
            }
            x->dat = table->getDiscriptions(x->name);
            continue;

		}
		Identifier_Data data1 = Identifier_Data(isInt ? ID_ARR_2_I : ID_ARR_2_C);
		data1.size[0] = x->size[0];
		data1.size[1] = x->size[1];
		table->pushSymbol(x->name, data1);
		x->dat = table->getDiscriptions(x->name);
	}
}



Var_data::~Var_data() {
	if (dimension == 1) initialData1.clear();
	if (dimension == 2) initialData2.clear();
}

void VarListNode::genCode(Synthesizer *out, MemoryAllocator *allocator, bool isGlobal) {
    for(auto *x : list)x->genCode(out, allocator, isGlobal);
}
void VarDefNode::genCode(Synthesizer *out, MemoryAllocator *allocator, bool isGlobal) {
    for(auto d : data){
        if(isGlobal) {
            if (d->dimension >= 1) {
                int size = d->dimension == 1 ? d->size[0] : d->size[1] * d->size[0];
                if(!init)allocator->allocGlobalMem(d->dat.uid, size * 4);
                else if(d->dimension == 1){
                    allocator->allocGlobalMem(d->dat.uid, d->initialData1);
                } else{
                    std::vector<int> dat;
                    for(const auto& i : d->initialData2){
                        for(int j : i){
                            dat.push_back(j);
                        }
                    }
                    allocator->allocGlobalMem(d->dat.uid, dat);
                }
            }
            else if(init) allocator->allocGlobalMem(d->dat.uid, std::vector<int>({d->initialData}));
            else allocator->allocGlobalMem(d->dat.uid, 4);
            continue;
        }
        if(d->dimension >= 1){
            int size = d->dimension == 1 ? d->size[0] : d->size[1] * d->size[0];
            allocator->allocLocalArr(d->dat.uid, size * 4);
            if(init){
                if(d->dimension == 1)
                    for(int i = 0; i < d->size[0]; i++)
                        allocator->saveArrCnst(d->dat.uid, d->initialData1[i], i * 4);
                else for(int i = 0; i < d->size[0]; i++)
                        for (int j = 0; j < d->size[1]; ++j)
                            allocator->saveArrCnst(d->dat.uid, d->initialData2[i][j], (i * d->size[1] + j) * 4);
            }
        } else if (init){
            int reg = allocator->loadToReg_writeOnly(d->dat.uid);
            out->text<<"li $"<<reg<<' '<<d->initialData<<std::endl;
        }
    }
}